package fr.grassaud.hmvc.info;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fr.grassaud.hmvc.component.Model;
import fr.grassaud.hmvc.component.View;
import fr.grassaud.hmvc.event.HMVCEvent;
import fr.grassaud.hmvc.event.OnModelEvent;
import fr.grassaud.hmvc.util.HMVCIntrospector;

public class ModelInfo {

    private Class<?> controllerClass;
    private Map<String, Method> methods;
    private Method initMethod;
    private Method releaseMethod;

    private final Field field;

    private Logger logger = LoggerFactory.getLogger(ModelInfo.class);

    public ModelInfo(Field field) {
	this.field = field;
	readInfo();

    }

    public String getName() {
	return field.getName();
    }

    private void readInfo() {
	if (!HMVCIntrospector.isModelComponent(field.getType())) {
	    logger.error("ERROR, the view of type {} should be annotated with {}", field.getType(),
		    View.class.getName());
	    throw new IllegalArgumentException("the model should be annotated with " + Model.class.getName());
	}

	controllerClass = HMVCIntrospector.getModelController(field.getType());

	methods = new HashMap<String, Method>();

	for (Method m : HMVCIntrospector.getAllMethods(field.getType())) {
	    if (HMVCIntrospector.isInitMethod(m)) {
		initMethod = m;
	    }
	    if (HMVCIntrospector.isReleaseMethod(m)) {
		releaseMethod = m;
	    }

	    if (m.isAnnotationPresent(OnModelEvent.class)) {
		OnModelEvent mAnnotation = m.getAnnotation(OnModelEvent.class);
		this.methods.put(mAnnotation.name(), m);
	    }
	}
    }

    public Class<?> getControllerClass() {
	return controllerClass;
    }

    public Method getInitMethod() {
	return initMethod;
    }

    public Class<?> getModelClass() {
	return field.getType();
    }

    public Field getField() {
	return this.field;
    }

    public Method getModelEventMethod(HMVCEvent event) {
	return methods.get(event.getName());
    }
    
    
    public Method getReleaseMethod() {
   	return this.releaseMethod;
       }

}
